package sdk

import (
	"time"

	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/common/thirdparty/facebook"
	"gddgame.cc/galaxy/common/thirdparty/google"
	"gddgame.cc/galaxy/common/thirdparty/mi"
	"gddgame.cc/galaxy/common/thirdparty/qq"
	"gddgame.cc/galaxy/common/thirdparty/wechat"
	app "gddgame.cc/galaxy/core/controllers/app"
	user "gddgame.cc/galaxy/core/controllers/user"
	"gddgame.cc/galaxy/core/models"
	"gddgame.cc/galaxy/utils/def"
)

// 目前平台代码是集成在游戏服务端
// 直接做url的映射controller

type AppPlatform interface {
	App() *models.App
	ValidAppToken(appId string, appToken string) (*models.App, error)
	ValidToken(token string) (*models.UserOpen, error)
	Login(username string, password string) (*models.UserOpen, error)
	GetOpen(openId string) (*models.UserOpen, error)
	GetUser(userId int) (*models.User, error)
	GetOpenList(openIds []string) ([]models.UserOpen, error)
	ChangeOpen(openId string, nickName string, avatar string) error
	SetRealInfo(openId string, idCard string, realName string) error
	GenerateAccessToken(openId string, policy map[string]interface{}, expire int) (string, error)
	GetFriendList(openId string, status bool, updateTime *time.Time) ([]models.UserOpen, error)
	IsFriend(openId string, friendOpenList []models.UserOpen) []bool
	SearchUserList(keyword string, page int, number int) ([]models.UserOpen, error)
	UpdateOpenPreferences(openId string, preferences map[string]string) error
	GetOpenStore(openId string, key string) (interface{}, error)
	UpdateOpenStore(openId string, key string, value interface{}) error
	InviteFriend(openId string, target string) error
	ConfirmFriend(openId string, target string, ok bool) error
	RegisterGuest() (*models.UserOpen, error)
	Oauth(channel string, code string, state string, userOpenId string) (*models.UserOpen, error)
	AppOauth(channel string, openId string, accessToken string, userOpenId string) (*models.UserOpen, error)
	AppOfflineOauth(channel string, openId string, nickname string, userOpenId string) (*models.UserOpen, error)
	OauthList(openId string) ([]string, error)
	SubmitFeedback(openId string, message string) error
	GetLeaderboard(identity string) (*models.AppLeaderboard, error)
	UpdateLeaderboard(openId string, leaderboard *models.AppLeaderboard, value int) (int, error)
	GetLeaderboardNumber(openId string, leaderboard *models.AppLeaderboard) (int, error)
}

type appPlatform struct {
	client *AppClient
	app    models.App
}

func newAppPlatform(context def.Context, client *AppClient) (*appPlatform, error) {
	platform := &appPlatform{
		client: client,
	}
	n, err := models.AppModel.Query().Where("=", "app_key", client.appKey).Find(&platform.app)
	if n == 0 {
		return nil, ValidExceptionDetail("App不存在", err)
	}
	if platform.app.AppSecret != client.appSecret {
		return nil, ValidException("AppSecret error")
	}

	if err := app.InitApp(context, client); err != nil {
		return nil, err
	}
	if err := user.InitUser(context, client); err != nil {
		return nil, err
	}
	// 初始化第三方平台
	platform.app.Wechat = wechat.NewClient(client, client.Cache("wechat"), platform.app.WechatAppId, platform.app.WechatAppSecret)
	platform.app.Facebook = facebook.NewClient(client, platform.app.FacebookAppId, platform.app.FacebookAppSecret)
	platform.app.QQ = qq.NewClient(client, client.Cache("qq"), platform.app.QQAppId, platform.app.QQAppSecret)
	platform.app.Google = google.NewClient(client, platform.app.GoogleAppId, platform.app.GoogleAppSecret)
	platform.app.Mi = mi.NewClient(client, platform.app.MiAppId, platform.app.MiAppSecret)
	return platform, nil
}

func (platform *appPlatform) App() *models.App {
	return &platform.app
}

func (platform *appPlatform) ValidAppToken(appId string, appToken string) (*models.App, error) {
	return app.ValidToken(platform.client, appId, appToken)
}

func (platform *appPlatform) ValidToken(token string) (*models.UserOpen, error) {
	return user.ValidToken(platform.client, &platform.app, token)
}

func (platform *appPlatform) Login(username string, password string) (*models.UserOpen, error) {
	return user.Login(platform.client, &platform.app, username, password)
}

func (platform *appPlatform) GetOpen(openId string) (*models.UserOpen, error) {
	return user.GetOpen(platform.client, &platform.app, openId)
}

func (platform *appPlatform) GetUser(userId int) (*models.User, error) {
	return user.GetUser(platform.client, userId)
}

func (platform *appPlatform) GetOpenList(openIds []string) ([]models.UserOpen, error) {
	return user.GetOpenList(platform.client, &platform.app, openIds)
}

func (platform *appPlatform) ChangeOpen(openId string, nickName string, avatar string) error {
	return user.ChangeOpen(platform.client, &platform.app, openId, nickName, avatar)
}

func (platform *appPlatform) SetRealInfo(openId string, idCard string, realName string) error {
	return user.SetRealInfo(platform.client, &platform.app, openId, idCard, realName)
}

func (platform *appPlatform) GenerateAccessToken(openId string, policy map[string]interface{}, expire int) (string, error) {
	return app.GenerateAccessToken(platform.client, &platform.app, openId, policy, expire)
}

func (platform *appPlatform) GetFriendList(openId string, status bool, updateTime *time.Time) ([]models.UserOpen, error) {
	return user.GetFriendList(platform.client, &platform.app, openId, status, updateTime)
}

func (platform *appPlatform) IsFriend(openId string, friendOpenList []models.UserOpen) []bool {
	return user.IsFriend(platform.client, &platform.app, openId, friendOpenList)
}

func (platform *appPlatform) SearchUserList(keyword string, page int, number int) ([]models.UserOpen, error) {
	return user.SearchUserList(platform.client, &platform.app, keyword, page, number)
}

func (platform *appPlatform) UpdateOpenPreferences(openId string, preferences map[string]string) error {
	return user.UpdateOpenPreferences(platform.client, &platform.app, openId, preferences)
}

func (platform *appPlatform) GetOpenStore(openId string, key string) (interface{}, error) {
	return user.GetOpenStore(platform.client, &platform.app, openId, key)
}

func (platform *appPlatform) UpdateOpenStore(openId string, key string, value interface{}) error {
	return user.UpdateOpenStore(platform.client, &platform.app, openId, key, value)
}

func (platform *appPlatform) InviteFriend(openId string, target string) error {
	return user.InviteFriend(platform.client, &platform.app, openId, target)
}

func (platform *appPlatform) ConfirmFriend(openId string, target string, ok bool) error {
	return user.ConfirmFriend(platform.client, &platform.app, openId, target, ok)
}

func (platform *appPlatform) RegisterGuest() (*models.UserOpen, error) {
	return user.RegisterGuest(platform.client, &platform.app)
}

func (platform *appPlatform) Oauth(channel string, code string, state string, userOpenId string) (*models.UserOpen, error) {
	return user.Oauth(platform.client, &platform.app, channel, code, state, userOpenId)
}

func (platform *appPlatform) AppOauth(channel string, openId string, accessToken string, userOpenId string) (*models.UserOpen, error) {
	return user.AppOauth(platform.client, &platform.app, channel, openId, accessToken, userOpenId)
}

func (platform *appPlatform) AppOfflineOauth(channel string, openId string, nickname string, userOpenId string) (*models.UserOpen, error) {
	return user.AppOfflineOauth(platform.client, &platform.app, channel, openId, nickname, userOpenId)
}

func (platform *appPlatform) OauthList(openId string) ([]string, error) {
	return user.OauthList(platform.client, &platform.app, openId)
}

func (platform *appPlatform) SubmitFeedback(openId string, message string) error {
	userOpen, err := user.GetOpen(platform.client, &platform.app, openId)
	if err != nil {
		return err
	}
	return app.SubmitFeedback(platform.client, &platform.app, userOpen, message)
}

func (platform *appPlatform) GetLeaderboard(identity string) (*models.AppLeaderboard, error) {
	return app.GetLeaderboard(platform.client, &platform.app, identity)
}

func (platform *appPlatform) UpdateLeaderboard(openId string, leaderboard *models.AppLeaderboard, value int) (int, error) {
	userOpen, err := user.GetOpen(platform.client, &platform.app, openId)
	if err != nil {
		return 0, err
	}
	return app.UpdateLeaderboard(platform.client, &platform.app, userOpen, leaderboard, value)
}

func (platform *appPlatform) GetLeaderboardNumber(openId string, leaderboard *models.AppLeaderboard) (int, error) {
	userOpen, err := user.GetOpen(platform.client, &platform.app, openId)
	if err != nil {
		return 0, err
	}
	return app.GetLeaderboardNumber(platform.client, &platform.app, userOpen, leaderboard)
}
